package com.qdhh.enrollment.controller.miniapp;

import com.qdhh.enrollment.common.BusinessException;
import com.qdhh.enrollment.common.Result;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qdhh.enrollment.config.ExamProperties;
import com.qdhh.enrollment.model.QuizQuestion;
import com.qdhh.enrollment.model.QuizSubmission;
import cn.dev33.satoken.stp.StpUtil;
import com.qdhh.enrollment.security.PermissionChecker;
import com.qdhh.enrollment.service.QuizService;
import com.qdhh.enrollment.service.QuizSubmissionService;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Tag(name = "小程序-考试模块", description = "小程序考试相关接口，包括获取试卷、提交答案、查询成绩等")
@RestController
@RequestMapping("/api/miniapp/quiz")
public class MiniappQuizController {

    private final QuizService quizService;
    private final QuizSubmissionService submissionService;
    private final ExamProperties examProperties;
    private final ObjectMapper objectMapper = new ObjectMapper();

    public MiniappQuizController(QuizService quizService,
                                  QuizSubmissionService submissionService,
                                  ExamProperties examProperties) {
        this.quizService = quizService;
        this.submissionService = submissionService;
        this.examProperties = examProperties;
    }

    @Operation(summary = "获取试卷", description = "获取考试试卷，需要登录认证和身份认证（identityVerified=1）")
    @GetMapping("/paper")
    public Result<Map<String, Object>> paper(
            @Parameter(description = "考试模式", example = "exam") @RequestParam(value = "mode", defaultValue = "exam") String mode,
            @Parameter(description = "题目总数", example = "10") @RequestParam(value = "total", defaultValue = "10") int total,
            @Parameter(description = "题型配额，格式：single:5,multiple:3,judge:2") @RequestParam(value = "typeQuota", required = false) String typeQuota) {
        // 检查身份认证：只有已认证的用户才能答题
        PermissionChecker.checkIdentityVerified();
        
        String studentId = currentStudentId();
        Map<String, Integer> quota = parseQuota(typeQuota);
        List<QuizQuestion> questions = quizService.pickForExam(total, quota);
        List<Map<String, Object>> questionViews = questions.stream()
            .map(this::toView)
            .collect(Collectors.toList());
        int used = submissionService.countAttempts(studentId);
        Map<String, Object> payload = new HashMap<>();
        payload.put("questions", questionViews);
        Map<String, Object> attempt = new HashMap<>();
        attempt.put("used", used);
        attempt.put("left", Math.max(0, 2 - used));
        payload.put("attempt", attempt);
        payload.put("mode", mode);
        return Result.success("OK", payload);
    }

    @Operation(summary = "提交答案", description = "提交考试答案，需要登录认证和身份认证（identityVerified=1）。每个学生最多可以提交2次")
    @PostMapping("/submit")
    public Result<Map<String, Object>> submit(@RequestBody QuizSubmitRequest requestBody) throws JsonProcessingException {
        // 检查身份认证：只有已认证的用户才能提交答案
        PermissionChecker.checkIdentityVerified();
        
        String studentId = currentStudentId();
        int used = submissionService.countAttempts(studentId);
        if (used >= 2) {
            return Result.failure(400, "No more attempts");
        }
        List<String> questionIds = requestBody.getQuestionIds();
        if (questionIds == null || questionIds.isEmpty()) {
            return Result.failure(400, "questionIds required");
        }
        List<QuizQuestion> questions = quizService.listByIds(questionIds);
        if (questions.isEmpty()) {
            return Result.failure(400, "Questions not found");
        }
        Map<String, String> answers = Optional.ofNullable(requestBody.getAnswers()).orElse(Collections.emptyMap());
        int score = quizService.score(answers, questions);
        boolean passed = score >= examProperties.getPassScore();

        QuizSubmission submission = new QuizSubmission();
        submission.setId(UUID.randomUUID().toString().replace("-", ""));
        submission.setStudentId(studentId); // 使用 student_id
        submission.setOpenid(studentId); // 兼容字段
        submission.setScore(score);
        submission.setPassed(passed ? 1 : 0);
        submission.setAttemptNo(used + 1);
        submission.setDetail(objectMapper.writeValueAsString(answers));
        submission.setCreatedAt(LocalDateTime.now());
        submissionService.saveSubmission(submission);

        int bestScore = submissionService.findBest(studentId)
            .map(QuizSubmission::getScore)
            .map(existing -> Math.max(existing, score))
            .orElse(score);

        Map<String, Object> payload = new HashMap<>();
        payload.put("score", score);
        payload.put("passed", passed);
        Map<String, Object> attempt = new HashMap<>();
        attempt.put("used", used + 1);
        attempt.put("left", Math.max(0, 2 - (used + 1)));
        payload.put("attempt", attempt);
        payload.put("bestScore", bestScore);
        return Result.success("OK", payload);
    }

    @Operation(summary = "查询成绩", description = "查询当前登录学生的考试成绩（最新成绩和最佳成绩），需要登录认证")
    @GetMapping("/result")
    public Result<Map<String, Object>> result() {
        String studentId = currentStudentId();
        Map<String, Object> payload = new HashMap<>();
        submissionService.findLatest(studentId).ifPresent(latest -> {
            Map<String, Object> latestMap = new HashMap<>();
            latestMap.put("score", latest.getScore());
            latestMap.put("passed", latest.getPassed() == 1);
            latestMap.put("createdAt", latest.getCreatedAt());
            payload.put("latest", latestMap);
        });
        submissionService.findBest(studentId).ifPresent(best -> {
            Map<String, Object> bestMap = new HashMap<>();
            bestMap.put("score", best.getScore());
            bestMap.put("passed", best.getPassed() == 1);
            bestMap.put("createdAt", best.getCreatedAt());
            payload.put("best", bestMap);
        });
        payload.putIfAbsent("latest", null);
        payload.putIfAbsent("best", null);
        return Result.success("OK", payload);
    }

    private Map<String, Integer> parseQuota(String quotaStr) {
        if (!StringUtils.hasText(quotaStr)) {
            return Collections.emptyMap();
        }
        Map<String, Integer> map = new HashMap<>();
        String[] entries = quotaStr.split(",");
        for (String entry : entries) {
            String[] kv = entry.split(":");
            if (kv.length == 2) {
                try {
                    map.put(kv[0].trim(), Integer.parseInt(kv[1].trim()));
                } catch (NumberFormatException ignored) {
                }
            }
        }
        return map;
    }

    private Map<String, Object> toView(QuizQuestion question) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", question.getId());
        map.put("question", question.getQuestion());
        map.put("options", parseJsonArray(question.getOptions()));
        map.put("type", question.getType());
        map.put("score", question.getScore());
        return map;
    }

    private List<String> parseJsonArray(String json) {
        if (!StringUtils.hasText(json)) {
            return Collections.emptyList();
        }
        try {
            return objectMapper.readValue(json,
                objectMapper.getTypeFactory().constructCollectionType(List.class, String.class));
        } catch (Exception e) {
            return Collections.emptyList();
        }
    }

    private String currentStudentId() {
        if (!StpUtil.isLogin()) {
            throw new BusinessException("未登录");
        }
        return StpUtil.getLoginIdAsString();
    }

    public static class QuizSubmitRequest {
        private Map<String, String> answers;
        private List<String> questionIds;

        public Map<String, String> getAnswers() {
            return answers;
        }

        public void setAnswers(Map<String, String> answers) {
            this.answers = answers;
        }

        public List<String> getQuestionIds() {
            return questionIds;
        }

        public void setQuestionIds(List<String> questionIds) {
            this.questionIds = questionIds;
        }
    }
}

